"""
This file is only used for simulation purpose because
 the posnet_overlay class knows the overlay entirely...
"""
from __future__ import generators
import os,sys
import sets
import random
from networkx.digraph import DiGraph
from posnet_overlay_node import posnet_overlay_node,posnet_semantic_query

from posnet_underlays import posnet_underlay_memory

class posnet_overlay(object):
	""" a posnet overlay """
	def __init__(self,Poset):
		object.__init__(self)
		self._poset = Poset
		self._overlay_nodes = []
		# the whole overlay topology is not maintained with a graph class or something like that
		# remember a posnet_overlay_node  know its neighbors
		self._underlay = posnet_underlay_memory()
		self.initialize()

	def initialize(self):
		""" add a first node to the overlay if it does not have one..."""
		if self.n_nodes() > 0: return
		node_id = len(self._overlay_nodes)
		new_node = posnet_overlay_node(self._poset,node_id)
		new_node.set_underlay(self._underlay)
		self._overlay_nodes.append(new_node)
		self._underlay.add(node_id,new_node)

	def get_Poset(self): return self._poset
	#---------------------------
	# overlay nodes
	#---------------------------

	# node (access, number...)
	def n_nodes(self):
		""" return the number of overlay nodes"""
		return len(self._overlay_nodes)
	def __len__(self):
		""" return the size of the overlay : number of nodes"""
		return self.n_nodes()
	def node(self,index):
		""" return the index^th node""" 
		if index < 0 or index >= len(self._overlay_nodes):
			raise Exception("invalid node requested with index "+str(index)) 
		return self._overlay_nodes[index]

	# random node
	def random_node_id(self):
		""" return a random node index"""
		indexes = range(len(self._overlay_nodes))
		index = random.choice(indexes)
		return index

	def add_node(self,insert_point = None):
		""" add a new overlay node to the overlay"""
		node_id = len(self._overlay_nodes)
		new_node = posnet_overlay_node(self._poset,node_id)
		new_node.set_underlay(self._underlay)	
		if insert_point is None: insert_point =  self.random_node_id()		
		self._overlay_nodes.append(new_node)
		self._underlay.add(node_id,new_node)
		# build join message
		new_node.send_join(insert_point)
		return node_id
	def write_dot(self,basename):	
		ff = file(basename+".txt","w")
		for node in self._overlay_nodes:
			print >>ff,node.tostring()
		ff.close()
		f = file(basename+".dot","w")
		f2 = file(basename+"-overlay.dot","w")
		print >>f,"digraph G {"
		print >>f2,"digraph G {"
		for node in self._overlay_nodes:
			towrite = dict()
			ext = node.write_dot(f,False) #True)
			for ext_link in ext:
				label_src,space_point_dst,overlay_node_dst,relation = ext_link
				try:
					vertex_id_dst = self.node(overlay_node_dst).vertex_id(space_point_dst)
					label_dst =  self.node(overlay_node_dst).get_label( vertex_id_dst )
					if relation != 'c2p':
						key =  ( node.id(),overlay_node_dst, relation)
						if towrite.has_key(key): towrite[key] += 1
						else: towrite[key] = 1
					if relation != "p2c": continue
					print >>f, label_src,"->",label_dst,"[label=\""+relation+"\",color=black,style=bold];"
				except Exception,e: 
					print "EXCEPTION",e,label_src,space_point_dst,overlay_node_dst,relation
					raise
			for key,number in towrite.items():	
				x,y,relation = key
				if number != 1:
					print >>f2,x,"->",y ,"[label=\""+relation+"("+str(number)+")\",color=black];"
				else: print >>f2,x,"->",y ,"[label=\""+relation+"\",color=black];"
		print >>f,"}"
		print >>f2,"}"
		f.close()
		f2.close()

from poset import read_poset
import pickle
from pprint import pprint

if __name__ == "__main__":
	Poset = dict()
	if len(sys.argv) > 1:
		#poset_file = sys.argv[1]
		#Poset = read_poset(poset_file)
		pass
	Poset = {"x":range(1,10),"y":range(1,10)} #,"z":range(7)}
	#Poset =  {"x": [0,1], "y": [0,1] }  
	overlay = posnet_overlay(Poset)
	#---------------------------------------
	id1 = overlay.node(0)
	#id3 = overlay.node(overlay.add_node())
	#---------------------------------------
	
	points = []
	def save(output):	
		overlay.write_dot(output)
		os.system("dot -T png -o "+output+".png "+output+".dot")
		os.system("dot -T png -o "+output+"-overlay.png "+output+"-overlay.dot")
		f = file(output+".pkl","wb")
		pickle.dump(points,f)
		f.close()
	#--	
	if len(sys.argv) > 1:
		# inject
		f = file(sys.argv[1],"rb")
		points_inject = pickle.load(f)
		f.close()
		for point in points_inject:	
			d,handle = point
			points.append( point )
			id1.overlay_add_handle(point[0],point[1])
	else:
		if False:
			i = 0
			while i < 70:
				d = dict()
				for x in Poset.keys():
					v = random.choice(Poset[x])
					d[x] = v
				points.append( (d,"data"+str(i)) )
				i += 1
			print "insert"
			for point in points:
				id1.overlay_add_handle(point[0],point[1])
		j = 0
		#---------------------
		id1.overlay_add_handle([4,2],"")
		id1.overlay_add_handle([4,9],"")
		id1.overlay_add_handle([1,9],"")
		id1.overlay_add_handle([8,10],"")
		id1.overlay_add_handle([3,2],"")
		id1.overlay_add_handle([10,1],"")
		id1.overlay_add_handle([9,4],"")
		id1.overlay_add_handle([2,5],"")
		id1.overlay_add_handle([9,1],"")
		id1.overlay_add_handle([9,9],"")
		id1.overlay_add_handle([3,5],"")
		id1.overlay_add_handle([7,3],"")
		#--------------------
		if not os.path.exists("draw/"): os.makedirs("draw/")	
		save("draw/graph"+str(j))
		while j < 10:
			print "JOIN--------------------------------------"
			sys.stdout.flush()
			sys.stderr.flush()
			j += 1
			overlay.add_node()
			save("draw/graph"+str(j))

